targets: Vec<Target>,
target_dir: Path,
doc_dir: Path,
- build: Vec<String>,
+ build: Vec<String>, // TODO: deprecated, remove
warnings: Vec<String>,
exclude: Vec<String>,
metadata: ManifestMetadata,
targets: Vec<Target>,
target_dir: String,
doc_dir: String,
- build: Option<Vec<String>>,
+ build: Option<Vec<String>>, // TODO: deprecated, remove
}
impl<E, S: Encoder<E>> Encodable<S, E> for Manifest {
targets: self.targets.clone(),
target_dir: self.target_dir.display().to_string(),
doc_dir: self.doc_dir.display().to_string(),
+ // TODO: deprecated, remove
build: if self.build.len() == 0 { None } else { Some(self.build.clone()) },
}.encode(s)
}
doctest: bool,
doc: bool,
dest: Option<String>,
- plugin: bool,
+ for_host: bool,
harness: bool, // whether to use the test harness (--test)
+ custom_build: bool,
}
impl Profile {
test: false,
doc: false,
dest: None,
- plugin: false,
+ for_host: false,
doctest: false,
+ custom_build: false,
harness: true,
}
}
self.doctest
}
- pub fn is_plugin(&self) -> bool {
- self.plugin
+ pub fn is_custom_build(&self) -> bool {
+ self.custom_build
+ }
+
+ /// Returns true if the target must be built for the host instead of the target.
+ pub fn is_for_host(&self) -> bool {
+ self.for_host
}
pub fn get_opt_level(&self) -> uint {
self
}
- pub fn plugin(mut self, plugin: bool) -> Profile {
- self.plugin = plugin;
+ /// Sets whether the `Target` must be compiled for the host instead of the target platform.
+ pub fn for_host(mut self, for_host: bool) -> Profile {
+ self.for_host = for_host;
self
}
self.harness = harness;
self
}
+
+ /// Sets whether the `Target` is a custom build script.
+ pub fn custom_build(mut self, custom_build: bool) -> Profile {
+ self.custom_build = custom_build;
+ self
+ }
}
impl<H: hash::Writer> hash::Hash<H> for Profile {
codegen_units,
debug,
rpath,
- plugin,
+ for_host,
ref dest,
harness,
env: _,
test: _,
doctest: _,
+
+ custom_build: _,
} = *self;
- (opt_level, codegen_units, debug, rpath, plugin, dest, harness).hash(into)
+ (opt_level, codegen_units, debug, rpath, for_host, dest, harness).hash(into)
}
}
targets: targets,
target_dir: target_dir,
doc_dir: doc_dir,
- build: build,
+ build: build, // TODO: deprecated, remove
warnings: Vec::new(),
exclude: exclude,
metadata: metadata,
}
}
+ /// Builds a `Target` corresponding to the `build = "build.rs"` entry.
+ pub fn custom_build_target(name: &str, src_path: &Path, profile: &Profile,
+ metadata: Option<Metadata>) -> Target {
+ Target {
+ kind: BinTarget,
+ name: name.to_string(),
+ src_path: src_path.clone(),
+ profile: profile.clone(),
+ metadata: metadata,
+ }
+ }
+
pub fn example_target(name: &str, src_path: &Path, profile: &Profile) -> Target {
Target {
kind: ExampleTarget,
if !visiting.insert(pkg.get_package_id()) { return }
let key = (pkg.get_package_id(), target.get_name());
- let req = if target.get_profile().is_plugin() {PlatformPlugin} else {req};
+ let req = if target.get_profile().is_for_host() {PlatformPlugin} else {req};
match self.requirements.entry(key) {
Occupied(mut entry) => { *entry.get_mut() = entry.get().combine(req); }
Vacant(entry) => { entry.set(req); }
ret.push(format!("{}{}", stem, self.target_exe));
} else {
if target.is_dylib() {
- let plugin = target.get_profile().is_plugin();
+ let plugin = target.get_profile().is_for_host();
let kind = if plugin {KindPlugin} else {KindTarget};
let (prefix, suffix) = try!(self.dylib(kind));
ret.push(format!("{}{}{}", prefix, stem, suffix));
}
jobs.enqueue(pkg, jq::StageStart, init);
- // First part of the build step of a target is to execute all of the custom
- // build commands.
+ // Old custom build system
+ // TODO: deprecated, remove
let mut build_cmds = Vec::new();
for (i, build_cmd) in pkg.get_manifest().get_build().iter().enumerate() {
- let work = try!(compile_custom(pkg, build_cmd.as_slice(), cx, i == 0));
+ let work = try!(compile_custom_old(pkg, build_cmd.as_slice(), cx, i == 0));
build_cmds.push(work);
}
let (freshness, dirty, fresh) =
//
// Each target has its own concept of freshness to ensure incremental
// rebuilds on the *target* granularity, not the *package* granularity.
- let (mut libs, mut bins, mut tests) = (Vec::new(), Vec::new(), Vec::new());
+ let (mut builds, mut libs, mut bins, mut tests) = (Vec::new(), Vec::new(),
+ Vec::new(), Vec::new());
for &target in targets.iter() {
let work = if target.get_profile().is_doc() {
let (rustdoc, desc) = try!(rustdoc(pkg, target, cx));
try!(rustc(pkg, target, cx, req))
};
- let dst = match (target.is_lib(), target.get_profile().is_test()) {
- (_, true) => &mut tests,
- (true, _) => &mut libs,
- (false, false) if target.get_profile().get_env() == "test" => &mut tests,
- (false, false) => &mut bins,
+ let dst = match (target.is_lib(),
+ target.get_profile().is_test(),
+ target.get_profile().is_custom_build()) {
+ (_, _, true) => &mut builds,
+ (_, true, _) => &mut tests,
+ (true, _, _) => &mut libs,
+ (false, false, _) if target.get_profile().get_env() == "test" => &mut tests,
+ (false, false, _) => &mut bins,
};
for (work, kind, desc) in work.into_iter() {
let (freshness, dirty, fresh) =
dst.push((job(dirty, fresh, desc), freshness));
}
}
+ jobs.enqueue(pkg, jq::StageCustomBuild, builds);
jobs.enqueue(pkg, jq::StageLibraries, libs);
jobs.enqueue(pkg, jq::StageBinaries, bins);
jobs.enqueue(pkg, jq::StageTests, tests);
Ok(())
}
-fn compile_custom(pkg: &Package, cmd: &str,
- cx: &Context, first: bool) -> CargoResult<Work> {
+// TODO: deprecated, remove
+fn compile_custom_old(pkg: &Package, cmd: &str,
+ cx: &Context, first: bool) -> CargoResult<Work> {
let root = cx.get_package(cx.resolve.root());
let profile = root.get_manifest().get_targets().iter()
.find(|target| target.get_profile().get_env() == cx.env())
// target directory (hence the || here).
let layout = cx.layout(pkg, match kind {
KindPlugin => KindPlugin,
- KindTarget if target.get_profile().is_plugin() => KindPlugin,
+ KindTarget if target.get_profile().is_for_host() => KindPlugin,
KindTarget => KindTarget,
});
// or their dependencies
let mut native_search_paths = HashSet::new();
for &(dep, target) in cx.dep_targets(pkg).iter() {
- if !target.get_profile().is_plugin() { continue }
+ if !target.get_profile().is_for_host() { continue }
each_dep(dep, cx, |dep| {
if dep.get_manifest().get_build().len() > 0 {
native_search_paths.insert(layout.native(dep));
name: String,
version: TomlVersion,
authors: Vec<String>,
- build: Option<TomlBuildCommandsList>,
+ build: Option<TomlBuildCommandsList>, // TODO: `String` instead
exclude: Option<Vec<String>>,
// package metadata
repository: Option<String>,
}
+// TODO: deprecated, remove
#[deriving(Decodable)]
pub enum TomlBuildCommandsList {
SingleBuildCommand(String),
self.bench.as_ref().unwrap().iter().map(|t| t.clone()).collect()
};
+ // processing the custom build script
+ let (new_build, old_build) = match project.build {
+ Some(SingleBuildCommand(ref cmd)) => {
+ if cmd.as_slice().ends_with(".rs") && layout.root.join(cmd.as_slice()).exists() {
+ (Some(Path::new(cmd.as_slice())), Vec::new())
+ } else {
+ (None, vec!(cmd.clone()))
+ }
+ },
+ Some(MultipleBuildCommands(ref cmd)) => (None, cmd.clone()),
+ None => (None, Vec::new())
+ };
+
// Get targets
let profiles = self.profile.clone().unwrap_or(Default::default());
let targets = normalize(lib.as_slice(),
bins.as_slice(),
+ new_build,
examples.as_slice(),
tests.as_slice(),
benches.as_slice(),
}
}
- let build = match project.build {
- Some(SingleBuildCommand(ref cmd)) => vec!(cmd.clone()),
- Some(MultipleBuildCommands(ref cmd)) => cmd.clone(),
- None => Vec::new()
- };
let exclude = project.exclude.clone().unwrap_or(Vec::new());
+ let has_old_build = old_build.len() >= 1;
+
let summary = try!(Summary::new(pkgid, deps,
self.features.clone()
.unwrap_or(HashMap::new())));
targets,
layout.root.join("target"),
layout.root.join("doc"),
- build,
+ old_build,
exclude,
metadata);
if used_deprecated_lib {
manifest.add_warning(format!("the [[lib]] section has been \
deprecated in favor of [lib]"));
}
+ if has_old_build {
+ manifest.add_warning(format!("warning: the old build command has been deprecated"));
+ }
Ok((manifest, nested_paths))
}
}
fn normalize(libs: &[TomlLibTarget],
bins: &[TomlBinTarget],
+ custom_build: Option<Path>,
examples: &[TomlExampleTarget],
tests: &[TomlTestTarget],
benches: &[TomlBenchTarget],
}
if target.plugin == Some(true) {
- ret = ret.into_iter().map(|p| p.plugin(true)).collect();
+ ret = ret.into_iter().map(|p| p.for_host(true)).collect();
}
ret
}
}
+ fn custom_build_target(dst: &mut Vec<Target>, cmd: &Path,
+ profiles: &TomlProfiles) {
+ let profiles = [
+ merge(Profile::default_dev().for_host(true), &profiles.dev),
+ merge(Profile::default_release().for_host(true), &profiles.release),
+ ];
+
+ let name = format!("build-script-{}", cmd.filestem_str().unwrap_or(""));
+
+ for profile in profiles.iter() {
+ dst.push(Target::custom_build_target(name.as_slice(),
+ cmd, profile, None));
+ }
+ }
+
fn example_targets(dst: &mut Vec<Target>, examples: &[TomlExampleTarget],
profiles: &TomlProfiles,
default: |&TomlExampleTarget| -> String) {
([], []) => ()
}
+ if let Some(custom_build) = custom_build {
+ custom_build_target(&mut ret, &custom_build, profiles);
+ }
example_targets(&mut ret, examples, profiles,
|ex| format!("examples/{}.rs", ex.name));
--- /dev/null
+use support::{project, execs};
+use hamcrest::{assert_that};
+
+fn setup() {
+}
+
+test!(custom_build_compiled {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ build = 'build.rs'
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("build.rs", r#"
+ invalid rust file, should trigger a build error
+ "#);
+ assert_that(p.cargo_process("build"),
+ execs().with_status(101));
+})
execs().with_status(0)
.with_stdout(format!(" Compiling foo v0.5.0 ({})\n",
p.url()))
- .with_stderr(""));
+ .with_stderr("warning: the old build command has been deprecated"));
})
test!(old_custom_multiple_build {
execs().with_status(0)
.with_stdout(format!(" Compiling foo v0.5.0 ({})\n",
p.url()))
- .with_stderr(""));
+ .with_stderr("warning: the old build command has been deprecated"));
})
test!(old_custom_build_failure {
"#);
assert_that(p.cargo_process("build"),
execs().with_status(101).with_stderr(format!("\
+warning: the old build command has been deprecated\n\
Failed to run custom build command for `foo v0.5.0 ({dir})
Process didn't exit successfully: `{}` (status=101)\n\
--- stderr\n\
"#);
assert_that(p.cargo_process("build"),
execs().with_status(101).with_stderr(format!("\
+warning: the old build command has been deprecated\n\
Failed to run custom build command for `foo v0.5.0 ({dir})
Process didn't exit successfully: `{}` (status=101)\n\
--- stderr\n\
mod test_cargo_bench;
mod test_cargo_clean;
mod test_cargo_compile;
+mod test_cargo_compile_custom_build;
mod test_cargo_compile_old_custom_build;
mod test_cargo_compile_git_deps;
mod test_cargo_compile_path_deps;